from django.contrib.auth.models import User
from django.db import models
from spargameproject.spargame.custom_models import ObfuscatedPKModel, PickledObjectField
import traceback

# Create your models here.
class Player(ObfuscatedPKModel):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=255, null=False, blank=False, unique=False)

    def getAvatar(self):
      avatar = self.getMetadata('avatar_img')
      return avatar or '/site_media/images/avatar-thumbnails/anonymous.png'

    def getActiveGameIds(self):
      try:
        result = []
        game_players = self.gameplayer_set.filter(game__completion_timestamp__isnull=True)
        for game_player in game_players:
          if not game_player.getMetadata('forfeit'):
            result.append(str(game_player.game.id))
        return ','.join(result)
      except Exception:
        traceback.print_exc()

    def setMetadata(self, data_key, data_value):
      metadata = self.playermetadata_set.get_or_create(data_key=data_key)[0]
      metadata.data_value = data_value
      metadata.save()

    def setMetadataWithMap(self, metadata_updates):
      for data_key, data_value in metadata_updates.iteritems():
        metadata = self.playermetadata_set.get_or_create(data_key=data_key)[0]
        metadata.data_value = data_value
        metadata.save()

    def getMetadata(self, data_key):
      return self.playermetadata_set.get_or_create(data_key=data_key)[0].data_value

class Game(ObfuscatedPKModel):
    name = models.CharField(max_length=255, null=False, blank=False, unique=False)
    creator_player = models.ForeignKey('Player', related_name='creator_games', db_index=True, null=False, blank=False)
    creation_timestamp = models.DateTimeField(db_index=True, null=False, blank=False, auto_now_add=True, editable=False)
    completion_timestamp = models.DateTimeField(null=True, blank=True, db_index=True)
    last_update_timestamp = models.DateTimeField(db_index=True, null=False, blank=False, auto_now_add=True, auto_now=True, editable=False)
    players = models.ManyToManyField(Player, related_name='player_games', through='GamePlayer')

    def getActiveGamePlayers(self):
      result = []
      game_players = self.gameplayer_set.all()
      for game_player in game_players:
        if self.isActivePlayer(game_player):
          result.append(game_player)
      return result

    def getOrderedActiveGamePlayersWithPlayerAtZero(self, player_id):
      result = []
      game_players = self.gameplayer_set.all()
      for game_player in game_players:
        if self.isActivePlayer(game_player):
          result.append(game_player)

      player_index = 0;
      for (count, game_player) in enumerate(result):
        if game_player.player.id == player_id:
          player_index = count
          break
      first_half = result[player_index:]
      second_half = result[:player_index]
      first_half.extend(second_half)
      return first_half

    def isActivePlayer(self, game_player):
      return not game_player.getMetadata('forfeit')

    def setMetadata(self, data_key, data_value):
      metadata = self.gamemetadata_set.get_or_create(data_key=data_key)[0]
      metadata.data_value = data_value
      metadata.save()

    def setMetadataWithMap(self, metadata_updates):
      for data_key, data_value in metadata_updates.iteritems():
        metadata = self.gamemetadata_set.get_or_create(data_key=data_key)[0]
        metadata.data_value = data_value
        metadata.save()

    def getMetadata(self, data_key):
      return self.gamemetadata_set.get_or_create(data_key=data_key)[0].data_value

class GamePlayer(ObfuscatedPKModel):
    player = models.ForeignKey(Player, null=False, blank=False)
    game = models.ForeignKey(Game, null=False, blank=False)
    creation_timestamp = models.DateTimeField(db_index=True, null=False, blank=False, auto_now_add=True, editable=False)

    def setMetadata(self, data_key, data_value):
      metadata = self.gameplayermetadata_set.get_or_create(data_key=data_key)[0]
      metadata.data_value = data_value
      metadata.save()

    def setMetadataWithMap(self, metadata_updates):
      for data_key, data_value in metadata_updates.iteritems():
        metadata = self.gameplayermetadata_set.get_or_create(data_key=data_key)[0]
        metadata.data_value = data_value
        metadata.save()

    def getMetadata(self, data_key):
      return self.gameplayermetadata_set.get_or_create(data_key=data_key)[0].data_value

    class Meta:
      unique_together = ('player', 'game')

class Play(ObfuscatedPKModel):
    player = models.ForeignKey(Player, null=False, blank=False)
    game = models.ForeignKey(Game, db_index=True, null=True, blank=True)
    play_type = models.CharField(db_index=True, max_length=255, null=False, blank=False)
    valid = models.BooleanField(null=False, blank=False, default=True)
    creation_timestamp = models.DateTimeField(db_index=True, null=False, blank=False, auto_now_add=True, editable=False)

    def setMetadata(self, data_key, data_value):
      metadata = self.playmetadata_set.get_or_create(data_key=data_key)[0]
      metadata.data_value = data_value
      metadata.save()

    def setMetadataWithMap(self, metadata_updates):
      for data_key, data_value in metadata_updates.iteritems():
        metadata = self.playmetadata_set.get_or_create(data_key=data_key)[0]
        metadata.data_value = data_value
        metadata.save()

    def getMetadata(self, data_key):
      return self.playmetadata_set.get_or_create(data_key=data_key)[0].data_value

class GameMetaData(ObfuscatedPKModel):
    game = models.ForeignKey(Game, db_index=True, null=False, blank=False)
    data_key = models.CharField(max_length=255, null=False, blank=False)
    data_value = PickledObjectField(null=False, blank=False)
    creation_timestamp = models.DateTimeField(db_index=True, null=False, blank=False, auto_now_add=True, editable=False)
    class Meta:
      unique_together = ('game', 'data_key')

class PlayerMetaData(ObfuscatedPKModel):
    player = models.ForeignKey(Player, db_index=True, null=False, blank=False)
    data_key = models.CharField(max_length=255, null=False, blank=False)
    data_value = PickledObjectField(null=False, blank=False)
    creation_timestamp = models.DateTimeField(db_index=True, null=False, blank=False, auto_now_add=True, editable=False)
    class Meta:
      unique_together = ('player', 'data_key')

class GamePlayerMetaData(ObfuscatedPKModel):
    game_player = models.ForeignKey(GamePlayer, db_index=True, null=False, blank=False)
    data_key = models.CharField(max_length=255, null=False, blank=False)
    data_value = PickledObjectField(null=False, blank=False)
    creation_timestamp = models.DateTimeField(db_index=True, null=False, blank=False, auto_now_add=True, editable=False)
    class Meta:
      unique_together = ('game_player', 'data_key')

class PlayMetaData(ObfuscatedPKModel):
    play = models.ForeignKey(Play, db_index=True, null=False)
    data_key = models.CharField(max_length=255, null=False, blank=False)
    data_value = PickledObjectField(null=False, blank=False)
    creation_timestamp = models.DateTimeField(db_index=True, null=False, blank=False, auto_now_add=True, editable=False)
    class Meta:
      unique_together = ('play', 'data_key')
